	package com.worklikedance.priceonline;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.content.Context;
import android.graphics.Point;
import android.os.AsyncTask;
import android.util.AttributeSet;
import com.worklikedance.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.worklikedance.model.GoldData;
import com.worklikedance.model.GoldItem;
import com.worklikedance.priceonline.R.color;
import com.worklikedance.util.Constant;
import com.worklikedance.util.CustomConnection;
import com.worklikedance.util.DOMParser;
import com.worklikedance.util.FetchingCode;
import com.worklikedance.util.PopoverView;
import com.worklikedance.util.PopoverView.PopoverViewDelegate;
import com.worklikedance.util.Utilities;

public class GoldPrice extends RelativeLayoutEx implements PopoverViewDelegate {
	public static final String CITY_KEY = "City";
	public static final String DATA_KEY = "Data";

	private LayoutInflater mInflater;
	private HashMap<String, Object> mCurrGoldPriceDict = null;
	private HashMap<String, Object> mPrevGoldPriceDict = null;
	private ArrayList<Object> mCurrGoldPrices;
	private ArrayList<Object> mPrevGoldPrices;

	// ListView Contents
	private GoldPriceAdapter mCurrAdapter;

	public GoldPrice(Context context) {
		this(context, null);
	}

	public GoldPrice(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public GoldPrice(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	public void fetchData(boolean allowLoadingOfflineData) {
		if (mFetchingData == true) {
			Log.d("GoldPrice", "Keep fetchData - Fetching task is running");
			
			return;
		}
		
		Log.d("GoldPrice", "Start fetchData gold price");
		mFetchingData = true;
		
		String allowLoadingOfflineDataString = "false";
		if (allowLoadingOfflineData) {
			allowLoadingOfflineDataString = "true";
		}
		
		String uri = Utilities.getUri( getResources().getString(R.string.gold_price_l) );
		new FetchGoldPriceTask().execute(uri, allowLoadingOfflineDataString);
	}
	
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();    
		
		mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		
		// Get latest updated datetime
		mLatestUpadateDateTime = Utilities.getData(Constant.LATEST_GOLD_PRICE_TIME_KEY, getContext());
		
		mPullToRefreshListView = (PullToRefreshListView) findViewById(R.id.price_list);
		mPullToRefreshListView.getLoadingLayoutProxy().setPullLabel( getResources().getString(R.string.pull_to_refresh_label) );
		mPullToRefreshListView.getLoadingLayoutProxy().setRefreshingLabel( getResources().getString(R.string.updating_title) );
		mPullToRefreshListView.getLoadingLayoutProxy().setReleaseLabel( getResources().getString(R.string.pull_to_refresh_label) );
		mPullToRefreshListView.getLoadingLayoutProxy().setLastUpdatedLabel("");

		// Set a listener to be invoked when the list should be refreshed.		
		mPullToRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
			@Override
			public void onRefresh(PullToRefreshBase<ListView> refreshView) {
				mManualFetchingData = true;
				fetchData(false);
			}
		});

		mListView = mPullToRefreshListView.getRefreshableView();		
		mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
		
		// Get a reference to the ListView holder
		mUpdatedTimeTextView = (TextView) this.findViewById(R.id.update_status_value);

		if (mCurrAdapter == null) {
			mCurrAdapter = new GoldPriceAdapter();			
			mListView.setAdapter(mCurrAdapter);

			showWaitingProgress(getResources().getString(R.string.updating_title));
			
			mManualFetchingData = true;
			fetchData(true);
		}
		else {
			mListView.setAdapter(mCurrAdapter);
			
			if (mCurrGoldPriceDict != null) {
				String updatedTime = (String) mCurrGoldPriceDict.get(Constant.UPDATED_DATE_KEY);
				updateLastUpdatedTime(updatedTime);
				
				mCurrAdapter.notifyDataSetChanged();
			}
		}
		
		mListView.setOnItemClickListener(new OnItemClickListener() {
			
			@Override
			public void onItemClick(AdapterView<?> arg0, View view, int position,
					long arg3) {				
				if (MainActivity.getInstance() != null) {
					MainActivity.getInstance().dismissPopup();
				}
				
//				mListView.setItemChecked(position, true);
				
				//position start from 1
				position -= 1;
				
				Object object = mCurrGoldPrices.get(position);
				if (object instanceof String) {
					return;
				}
				
				RelativeLayout rootView = GoldPrice.this;
				mPopoverView = new PopoverView(mContext, R.layout.popover_gold_view);

				int width = view.getWidth();
				int height = Utilities.getDP(mContext, 110);				
								
				mPopoverView.mRowIndex = position;
				mPopoverView.setContentSizeForViewInPopover(new Point(width, height));
				mPopoverView.setDelegate(GoldPrice.this);
				mPopoverView.showPopoverFromRectInViewGroup(rootView, PopoverView.getFrameForView(view), PopoverView.PopoverArrowDirectionAny, true);				
			}
		});		
	}
	
	private class FetchGoldPriceTask extends AsyncTask<String, Void, Integer> {
		String updateTime = "";
		HashMap<String, Object> goldPriceDict = null;
		HashMap<String, Object> prevGoldPriceDict = null;
		
		@Override
		protected Integer doInBackground(String... params) {
			boolean allowLoadingOfflineData = Boolean.parseBoolean(params[1]);
			boolean loadedOfflineData = false;
			boolean initData = false;
			
			String xmlDocument = "";

			try {
				xmlDocument = CustomConnection.executeHttpGet(params[0]);
			} 
			catch (Exception e) {
				e.printStackTrace();

				if (allowLoadingOfflineData) {
					xmlDocument = Utilities.getData(Constant.LATEST_GOLD_PRICE_KEY, mContext);
					loadedOfflineData = true;
				}
				else {
					return FetchingCode.NoNetwork.ordinal();
				}
			}

			try {
				if (xmlDocument == null) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				xmlDocument = xmlDocument.trim();
				
				if (xmlDocument.equals("")) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				if (xmlDocument.startsWith("<?xml") == false) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				NodeList nodes = DOMParser.queryNodes(xmlDocument, "/root/ratelist", null, null);
				if (nodes == null || nodes.getLength() < 1) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				Node rateListNode = nodes.item(0);
				if (rateListNode == null) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				NamedNodeMap attributes = rateListNode.getAttributes();
				if (attributes == null) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				Node updateTimeNode = attributes.getNamedItem("updated");
				if (updateTimeNode == null) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				updateTime = updateTimeNode.getTextContent();
				if (updateTime == null || updateTime.length() == 0) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				//"04:17:53 PM 10/09/2014"
				updateTime = Utilities.convertStringToDateString(updateTime, "hh:mm:ss a dd/MM/yyyy", Constant.UPDATED_DATE_TIME_FORMAT);
				Date updateDateTime = Utilities.convertStringToDate(updateTime, Constant.UPDATED_DATE_TIME_FORMAT);
				
				// Is new date time?
				if (mLatestUpadateDateTime != null && mLatestUpadateDateTime.length() > 0) {
					Date udpatedDateTime = Utilities.convertStringToDate(mLatestUpadateDateTime, Constant.UPDATED_DATE_TIME_FORMAT);
					
					if (Utilities.compareDateWithoutSecond(updateDateTime, udpatedDateTime) <= 0) {
						
						if (mCurrGoldPriceDict != null) {
							return FetchingCode.SameData.ordinal();	
						}
						
						initData = true;
						
						// Parse saved data
						if (loadedOfflineData == false) {
							xmlDocument = Utilities.getData(Constant.LATEST_GOLD_PRICE_KEY, mContext);
							updateTime = mLatestUpadateDateTime;
						}
					}
					
					prevGoldPriceDict = mCurrGoldPriceDict;
				}
				
				if (goldPriceDict == null) {
					goldPriceDict = new HashMap<String, Object>();
				}
				
				// Updated date time
				goldPriceDict.put(Constant.UPDATED_DATE_KEY, updateTime);
				
				// Gold data for each city
				ArrayList<GoldData> goldList = new ArrayList<GoldData>(); 
				
				NodeList cityNodes = rateListNode.getChildNodes();
				for (int i = 0; i < cityNodes.getLength(); i ++) {
					Node city = cityNodes.item(i);
					if (city == null) {
						continue;
					}
					
					NamedNodeMap attrs = city.getAttributes();
					if (attrs == null) {
						continue;
					}
					
					Node cityNode = attrs.getNamedItem("name");
					if (cityNode == null) {
						continue;
					}
					
					String cityName = cityNode.getTextContent();
					if (cityName == null || cityName.length() == 0) {
						continue;
					}
					
					GoldData goldData = new GoldData(cityName, new ArrayList<GoldItem>());
					
					NodeList items = city.getChildNodes();
					for (int j = 0; j < items.getLength(); j ++) {
						Node item = items.item(j);
						if (item == null) {
							continue;
						}
						
						NamedNodeMap itemAttrs = item.getAttributes();
						if (itemAttrs == null) {
							continue;
						}
						
						Node typeNode = itemAttrs.getNamedItem(Constant.TYPE_KEY);
						if (typeNode == null) {
							continue;
						}
						
						Node buyNode = itemAttrs.getNamedItem(Constant.BUY_KEY);
						if (buyNode == null) {
							continue;
						}
						
						Node sellNode = itemAttrs.getNamedItem(Constant.SELL_KEY);
						if (sellNode == null) {
							continue;
						}
						
						double sellPrice = Double.parseDouble(sellNode.getTextContent());
						double buyPrice = Double.parseDouble(buyNode.getTextContent());
						
						goldData.addGoldItem( new GoldItem(typeNode.getTextContent(), sellPrice, buyPrice) );
					}
					
					goldList.add(goldData);	
				}
				
				if (goldList != null && goldList.size() > 0) {
					goldPriceDict.put(Constant.DATA_KEY, goldList);
				}
				
				// Keep data for offline mode
				if (loadedOfflineData == false && initData == false) {
					String xmlPriceTmp = Utilities.getData(Constant.LATEST_GOLD_PRICE_KEY, mContext);
					
					Utilities.storeData(Constant.LATEST_GOLD_PRICE_KEY, xmlDocument, mContext);
					Utilities.storeData(Constant.LATEST_GOLD_PRICE_TIME_KEY, updateTime, mContext);

					if ( xmlPriceTmp != null && xmlPriceTmp.length() > 0 ) {
						Utilities.storeData(Constant.OLD_GOLD_PRICE_KEY, xmlPriceTmp, mContext);	
					}
				}
				
				if (prevGoldPriceDict == null) {
					String prevXmlDocument = Utilities.getData(Constant.OLD_GOLD_PRICE_KEY, mContext);
					prevGoldPriceDict = parsePrevGoldPrice(prevXmlDocument);
				}
			} 
			catch (Exception e) {
			}

			return FetchingCode.Success.ordinal();
		}

		@Override
		protected void onPostExecute(Integer result) {
			Log.d("GoldPrice", "Finish fetchData gold price, code: " + result);
			
			mFetchingData = false;
			
			if (GoldPrice.this != null) {
				hideWaitingProgress();
			}

			if (mPullToRefreshListView != null) {
				mPullToRefreshListView.onRefreshComplete();	
			}
			
			if (mManualFetchingData && mContext != null) {
				if (result == FetchingCode.SameData.ordinal()) {
					alert(mContext.getString(R.string.gia_vang_moi_nhat));
				}
				else if (result == FetchingCode.NoNetwork.ordinal()) {
					alert(mContext.getString(R.string.no_network));
				}

				mManualFetchingData = false;
			}
			
			if (result != FetchingCode.Success.ordinal()) {
				return;
			}
			
			mLatestUpadateDateTime = updateTime;
			mCurrGoldPriceDict = goldPriceDict;
			mPrevGoldPriceDict = prevGoldPriceDict;
			
			// TODO: Refactor later! Remove mCurrGoldPriceDict, mPrevGoldPriceDict
			mCurrGoldPrices = new ArrayList<Object>();
			mPrevGoldPrices = new ArrayList<Object>();

			if (mCurrGoldPriceDict != null) {
				feedingData( (ArrayList<GoldData>) mCurrGoldPriceDict.get(Constant.DATA_KEY), mCurrGoldPrices );	
			}

			if (mPrevGoldPriceDict != null) {
				feedingData( (ArrayList<GoldData>) mPrevGoldPriceDict.get(Constant.DATA_KEY), mPrevGoldPrices );
			}

			// Update date time
			updateLastUpdatedTime(mLatestUpadateDateTime);	
			
			// Update listview
			if (mCurrAdapter != null) {
				mCurrAdapter.notifyDataSetChanged();	
			}
		}
	}

	private HashMap<String, Object> parsePrevGoldPrice(String xmlDocument) {
		if (xmlDocument.equals("")) {
			return null;
		}
		
		if (xmlDocument.startsWith("<?xml") == false) {
			return null;
		}
		
		NodeList nodes = DOMParser.queryNodes(xmlDocument, "/root/ratelist", null, null);
		if (nodes == null || nodes.getLength() < 1) {
			return null;
		}
		
		Node rateListNode = nodes.item(0);
		if (rateListNode == null) {
			return null;
		}
		
		NamedNodeMap attributes = rateListNode.getAttributes();
		if (attributes == null) {
			return null;
		}
		
		Node updateTimeNode = attributes.getNamedItem("updated");
		if (updateTimeNode == null) {
			return null;
		}
		
		String updateTime = updateTimeNode.getTextContent();
		updateTime = Utilities.convertStringToDateString(updateTime, "hh:mm:ss a dd/MM/yyyy", Constant.UPDATED_DATE_TIME_FORMAT);
		
		HashMap<String, Object> dict = new HashMap<String, Object>();
		
		// Updated date time
		dict.put(Constant.UPDATED_DATE_KEY, updateTime);
		
		// Gold data for each city
		ArrayList<GoldData> goldList = new ArrayList<GoldData>(); 
		
		NodeList cityNodes = rateListNode.getChildNodes();
		for (int i = 0; i < cityNodes.getLength(); i ++) {
			Node city = cityNodes.item(i);
			if (city == null) {
				continue;
			}
			
			NamedNodeMap attrs = city.getAttributes();
			if (attrs == null) {
				continue;
			}
			
			Node cityNode = attrs.getNamedItem("name");
			if (cityNode == null) {
				continue;
			}
			
			String cityName = cityNode.getTextContent();
			if (cityName == null || cityName.length() == 0) {
				continue;
			}
			
			GoldData goldData = new GoldData(cityName, new ArrayList<GoldItem>());
			
			NodeList items = city.getChildNodes();
			for (int j = 0; j < items.getLength(); j ++) {
				Node item = items.item(j);
				if (item == null) {
					continue;
				}
				
				NamedNodeMap itemAttrs = item.getAttributes();
				if (itemAttrs == null) {
					continue;
				}
				
				Node typeNode = itemAttrs.getNamedItem(Constant.TYPE_KEY);
				if (typeNode == null) {
					continue;
				}
				
				Node buyNode = itemAttrs.getNamedItem(Constant.BUY_KEY);
				if (buyNode == null) {
					continue;
				}
				
				Node sellNode = itemAttrs.getNamedItem(Constant.SELL_KEY);
				if (sellNode == null) {
					continue;
				}
				
				double sellPrice = Double.parseDouble(sellNode.getTextContent());
				double buyPrice = Double.parseDouble(buyNode.getTextContent());
				
				goldData.addGoldItem( new GoldItem(typeNode.getTextContent(), sellPrice, buyPrice) );
			}
			
			goldList.add(goldData);	
		}
		
		if (goldList != null && goldList.size() > 0) {
			dict.put(Constant.DATA_KEY, goldList);
		}
		
		return dict;
	}
	
	private void feedingData(ArrayList<GoldData> dataSource, ArrayList<Object> arrayList) {
		for (int i = 0; i < dataSource.size(); i++) {
			GoldData goldData = dataSource.get(i);

			String city = goldData.getCity();
			arrayList.add(city);
			
			ArrayList<GoldItem> goldItemList = goldData.getGoldItemArray();
			arrayList.addAll(goldItemList);
		}
	}	

	@Override
	public void popoverViewWillShow(PopoverView view) {
		Log.i("POPOVER", "Will show");
		
		RelativeLayout detailInfo = view.getPopoverView();

		TextView textView1 = (TextView) detailInfo.findViewById(R.id.preTimeTextView);
		TextView preBuyTextView = (TextView) detailInfo.findViewById(R.id.preBuyTextView);
		TextView preSellTextView = (TextView) detailInfo.findViewById(R.id.preSellTextView);

		TextView textView4 = (TextView) detailInfo.findViewById(R.id.curTimeTextView);
		TextView curBuyTextView = (TextView) detailInfo.findViewById(R.id.curBuyTextView);
		TextView curSellTextView = (TextView) detailInfo.findViewById(R.id.curSellTextView);
		
		GoldItem currentData = (GoldItem) mCurrGoldPrices.get(view.mRowIndex);
		
		GoldItem prevData  = null;
		if (mPrevGoldPrices != null && view.mRowIndex < mPrevGoldPrices.size()) {
			prevData = (GoldItem) mPrevGoldPrices.get(view.mRowIndex);	
		}

		// Previous gold price
		String dateTime = "";
		if (mPrevGoldPriceDict != null) {
			dateTime = (String)mPrevGoldPriceDict.get(Constant.UPDATED_DATE_KEY);
			
			if (dateTime != null && dateTime.length() > 0) {
				dateTime = mContext.getString(R.string.before) + " " + Utilities.convertStringToDateString(dateTime, 
						Constant.UPDATED_DATE_TIME_FORMAT, Constant.CALLOUT_UPDATED_DATE_TIME_FORMAT);
			}
			else {
				dateTime = mContext.getString(R.string.before);
			}
		}
		else {
			dateTime = mContext.getString(R.string.before);
		}
		
		textView1.setText(dateTime);
				
		// Current gold price
		dateTime = "";
		dateTime = (String)mCurrGoldPriceDict.get(Constant.UPDATED_DATE_KEY);

		if (dateTime != null && dateTime.length() > 0) {
			dateTime = mContext.getString(R.string.current) + " " + Utilities.convertStringToDateString(dateTime, 
					Constant.UPDATED_DATE_TIME_FORMAT, Constant.CALLOUT_UPDATED_DATE_TIME_FORMAT);
		}
		else {
			dateTime = mContext.getString(R.string.before);
		}
		
		textView4.setText(dateTime);
		
		// Change value
		TextView buyValueChangeTextView = (TextView) detailInfo.findViewById(R.id.buyValueChangeTextView);
		TextView buyPercentChangeTextView = (TextView) detailInfo.findViewById(R.id.buyPercentChangeTextView);
		TextView sellValueChangeTextView = (TextView) detailInfo.findViewById(R.id.sellValueChangeTextView);
		TextView sellPercentChangeTextView = (TextView) detailInfo.findViewById(R.id.sellPercentChangeTextView);
		TextView changeTextView = (TextView) detailInfo.findViewById(R.id.changeTextView);

		double curBuy = currentData.getBuyPrice()*1000;
		double curSell = currentData.getSellPrice()*1000;
		double preBuy = 0;
		double preSell = 0;
		
		if (prevData != null) {
			preBuy = prevData.getBuyPrice()*1000;
			preSell = prevData.getSellPrice()*1000;
		}
		else {			
			changeTextView.setTextColor(color.black_pure);			
		}
		
		setValueTextViews(curBuy, preBuy, NUMBER_FORMAT, curBuyTextView, preBuyTextView, buyValueChangeTextView, buyPercentChangeTextView, null);
		setValueTextViews(curSell, preSell, NUMBER_FORMAT, curSellTextView, preSellTextView, sellValueChangeTextView, sellPercentChangeTextView, null);		
	}

	@Override
	public void popoverViewDidShow(PopoverView view) {
		Log.i("POPOVER", "Did show");
	}

	@Override
	public void popoverViewWillDismiss(PopoverView view) {
		Log.i("POPOVER", "Will dismiss");
	}

	@Override
	public void popoverViewDidDismiss(PopoverView view) {
		Log.i("POPOVER", "Did dismiss");
		mPopoverView = null;
	}
	
	public class GoldPriceAdapter extends BaseAdapter {	
				
		public final static int TYPE_SECTION_HEADER = 0;

		public GoldPriceAdapter()
		{		
			super();
		}
				
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {			
			Object itemData = mCurrGoldPrices.get(position);
			
			//Data row
			if (itemData instanceof GoldItem) {
				return createDataView(position, convertView);
			}
			//subheader of bydisposition
			else {								
				return createHeaderView(position, convertView, parent);
			}
		}
		
		private SJCPriceHolder createChildHolder(View convertView) {
			SJCPriceHolder holder = new SJCPriceHolder();
			
			holder.title = (TextView) convertView.findViewById(R.id.gold_title);
			holder.buy = (TextView) convertView.findViewById(R.id.buy_price);
			holder.sell = (TextView) convertView.findViewById(R.id.sell_price);
			holder.buyDiff = (TextView) convertView.findViewById(R.id.buy_price_diff);
			holder.sellDiff = (TextView) convertView.findViewById(R.id.sell_price_diff);
			holder.buyPer = (TextView) convertView.findViewById(R.id.buy_price_per);
			holder.sellPer = (TextView) convertView.findViewById(R.id.sell_price_per);
			holder.buyEmptyLine = convertView.findViewById(R.id.buyEmptyView);
			holder.sellEmptyLine = convertView.findViewById(R.id.sellEmptyView);
			
			return holder;
		}
				
		
		public View createDataView(final int position, View convertView) {
			
			// Gold price data
			GoldItem goldItem = (GoldItem) mCurrGoldPrices.get(position);
			
			GoldItem preGoldItem = null;
			
			if (mPrevGoldPrices != null && position < mPrevGoldPrices.size()) {
				preGoldItem = (GoldItem) mPrevGoldPrices.get(position);
			}
			
			SJCPriceHolder holder;
			
			if ((convertView == null) || (convertView.getId() != R.id.goldPriceRow)) {
				final View view = mInflater.inflate(R.layout.price_item_row, null, false);

				holder = createChildHolder(view);
							
				view.setTag(holder);
				
//				view.setOnClickListener(new OnClickListener() {
//					
//					@Override
//					public void onClick(View v) {
//						if (mListener != null) {
//							mListener.onClickRowAt(0, position, view);
//						}												
//					}
//				});
				
				convertView = view;
			}
			else {			
				Object tagObject = convertView.getTag();
				if (tagObject != null && tagObject instanceof SJCPriceHolder) {
					holder = (SJCPriceHolder)tagObject;
				}
				else {
					holder = createChildHolder(convertView);
					convertView.setTag(holder);
				}
			}
			
			double curBuy = goldItem.getBuyPrice()*1000;
			double curSell = goldItem.getSellPrice()*1000;
			double preBuy = 0;
			double preSell = 0;
			
			if (preGoldItem != null) {
				preBuy = preGoldItem.getBuyPrice()*1000;
				preSell = preGoldItem.getSellPrice()*1000;
			}
			
			holder.title.setText( goldItem.getGoldTitle() );
			
			setValueTextViews(curBuy, preBuy, NUMBER_FORMAT, holder.buy, holder.buyDiff, holder.buyPer, holder.buyEmptyLine);
			setValueTextViews(curSell, preSell, NUMBER_FORMAT, holder.sell, holder.sellDiff, holder.sellPer, holder.sellEmptyLine);
			
			return convertView;
		}
		
		
		
		private CityHolder createGroupdHolder(View convertView) {
			CityHolder holder = new CityHolder();

			TextView tv = (TextView) convertView.findViewById(R.id.list_header_title);		
			holder.title = tv;
			
			return holder;
		}
				
		public View createHeaderView(final int position, View convertView, ViewGroup parent) {			
			String city = (String)mCurrGoldPrices.get(position);
			CityHolder holder;
			
			if ((convertView == null) || (convertView.getId() != R.id.goldPriceHeader)) {
				convertView = mInflater.inflate(R.layout.price_item_header, parent, false);

				holder = createGroupdHolder(convertView);

				convertView.setTag(holder);
			}
			else {
				Object tagObject = convertView.getTag();
				if (tagObject != null && tagObject instanceof CityHolder) {
					holder = (CityHolder)tagObject;
				}
				else {
					holder = createGroupdHolder(convertView);
					convertView.setTag(holder);
				}			
			}
			
			if (city != null && holder.title != null) {
				holder.title.setText(city);
			}			
			
			return convertView;
		}
		
		private class CityHolder {
			public TextView title = null;
		}
		
		private class SJCPriceHolder {
			public TextView title = null;
			public TextView buy = null;
			public TextView sell = null;
			public TextView buyDiff = null;
			public TextView sellDiff = null;
			public TextView buyPer = null;
			public TextView sellPer = null;
			public View buyEmptyLine;
			public View sellEmptyLine;
						
			public int rowIndex;
		}

		@Override
		public int getCount() {
			if (mCurrGoldPrices == null) {
				return 0;
			}
			return mCurrGoldPrices.size();
		}

		@Override
		public Object getItem(int position) {			
			return null;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}
	}
}